package ua.edu.nuos.jeetraining2012.cms.util.servlet;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class CmsServlet extends HttpServlet {
    protected Logger logger = LoggerFactory.getLogger(getClass());

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) {
        invokeActionMethod(request, response);
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) {
        invokeActionMethod(request, response);
    }

    /**
     * Parse PATHINFO variable extract action name and invoke method nameAction
     *
     * @param request  Request object
     * @param response Response object
     */
    protected void invokeActionMethod(HttpServletRequest request, HttpServletResponse response) {
        logger.debug("invokeActionMethod() getPathinfo() -  " + request.getPathInfo());
        response.setContentType("text/html; charset=utf-8");
        String actionName = request.getPathInfo();
        String invokeMethodName;
        if ((actionName == null) || actionName.isEmpty() || actionName.equals("/")) {
            invokeMethodName = "indexAction";
        } else {
            int slashPos = actionName.indexOf('/', 1);
            if (slashPos == -1) {
                invokeMethodName = actionName.substring(1) + "Action";
            } else {
                invokeMethodName = actionName.substring(1, slashPos) + "Action";
            }
        }

        logger.debug("Trying to invoke method " + invokeMethodName);
        try {
            Method m = getClass().getMethod(invokeMethodName, HttpServletRequest.class, HttpServletResponse.class);
            m.invoke(this, request, response);
            return;
        } catch (InvocationTargetException e) {
            logger.error("Can't invoke method " + invokeMethodName + " InvocationTargetException occured. Cause: " + e.getCause());
        } catch (NoSuchMethodException |
                IllegalArgumentException |
                IllegalAccessException e) {
            logger.error("Can't invoke method " + invokeMethodName, e);
        }
        errorAction(request, response);
    }


    /**
     * Default implementation of errorAction
     *
     * @param request  Request  object
     * @param response Response object
     */
    protected void errorAction(HttpServletRequest request, HttpServletResponse response) {
        try {
            RequestDispatcher rd = request.getRequestDispatcher("/unknownpath.jspx");
            rd.forward(request, response);
        } catch (ServletException | IOException e) {
            logger.error("Forward error", e);
        }
    }

    /**
     * Return request url in form schema://host:port/contextpath
     *
     * @param  request HttpServletRequest from which URL will be built
     * @return Request URL
     */
    protected String getRequestURL(HttpServletRequest request) {
        return request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath();
    }
}
